package com.swt.gap.common.graph;

import com.swt.gap.common.constant.CommonConstant;
import org.neo4j.graphalgo.BetweennessCentralityProc;
import org.neo4j.graphalgo.GetNodeFunc;
import org.neo4j.graphalgo.LouvainProc;
import org.neo4j.graphalgo.PageRankProc;
import org.neo4j.graphdb.*;
import org.neo4j.graphdb.factory.GraphDatabaseFactory;
import org.neo4j.internal.kernel.api.exceptions.KernelException;
import org.neo4j.kernel.impl.proc.Procedures;
import org.neo4j.kernel.internal.GraphDatabaseAPI;
import org.springframework.stereotype.Component;

import java.io.File;
import java.util.List;

import static java.util.Arrays.asList;

/**
 * 请填写说明
 *
 * @author sx
 * @date 2019/9/16 23:23
 */
@Component
public class EmbeddedNeo4j {

    private static GraphDatabaseService graphDatabaseService;

    public EmbeddedNeo4j() {
        File file = new File(CommonConstant.GRAPH_DATA);
        graphDatabaseService = new GraphDatabaseFactory().newEmbeddedDatabase(file);
        Procedures procedures = ((GraphDatabaseAPI) graphDatabaseService).getDependencyResolver()
                .resolveDependency(Procedures.class, DependencyResolver.SelectionStrategy.FIRST);
        List<Class<?>> algoProcedures = asList(
                BetweennessCentralityProc.class,
                LouvainProc.class,
                GetNodeFunc.class,
                PageRankProc.class);
        algoProcedures.forEach((proc) -> {
            try {
                procedures.registerProcedure(proc);
            } catch (KernelException e) {
                throw new RuntimeException("Error registering "+proc,e);
            }
        });
    }

    public GraphDatabaseService getGraphDatabaseService() {
        return graphDatabaseService;
    }

    public void shutdown(){
        System.out.println( "Shutting down database ..." );
        graphDatabaseService.shutdown();
    }

    private static void registerShutdownHook(final GraphDatabaseService graphDB) {
        /*为了确保neo4j数据库的正确关闭，我们可以添加一个关闭钩子方法 registerShutdownHook。
         *这个方法的意思就是在jvm中增加一个关闭的钩子，
         *当jvm关闭的时候，会执行系统中已经设置的所有通过方法addShutdownHook添加的钩子，
         *当系统执行完这些钩子后，jvm才会关闭。
         *所以这些钩子可以在jvm关闭的时候进行内存清理、对象销毁等操作。*/
        Runtime.getRuntime().addShutdownHook(
                new Thread() {
                    @Override
                    public void run() {
                        //Shutdown the Database
                        System.out.println("Server is shutting down");
                        graphDB.shutdown();
                    }
                }
        );
    }
}

